using System;
using System.Drawing;
using System.Collections.Generic;
using OpenTK;

using OpenTK.Graphics.OpenGL;
using OpenTK.Audio;

using OpenTK.Input;
using OpenTK;
namespace Xeno.Core
{
    public class XenoApp : GameWindow
    {
        public static XenoRenderTarget FrameBufferTarget;
        public static XenoTexture2D FrameBuffer;
        public static XenoTextureDepth FrameDepth;
        public static XenoApp Instance = null;
        public static double FrameTime = 0.0f;
        public List<XenoFilter> Filters { get; set; }
        /// <summary>Creates a 800x600 window with the specified title.</summary>
        public XenoApp()
            : base(800, 600, OpenTK.Graphics.GraphicsMode.Default, "OpenTK Quick Start Sample")
        {
            VSync = VSyncMode.Off;
            XenoCore.DisplayWidth = Width;
            XenoCore.DisplayHeight = Height;
            ResetEngine();
        }

        public XenoApp(int width, int height, string title)
            : base(width, height, OpenTK.Graphics.GraphicsMode.Default, title)
        {
            VSync = VSyncMode.Off;
            XenoCore.DisplayWidth = width;
            XenoCore.DisplayHeight = height;
     
            ResetEngine();
        }

        public void ResetEngine()
        {
            Instance = this;
            XenoCore.CurrentApp = this;
            XenoCore.CurrentScene = new XenoGraph();
            XenoCore.CurrentView = XenoFactory.Node.Camera("View Camera", XenoCore.CurrentScene.RootNode);
            XenoInput.Init();
            XenoText.Init();
            FrameBufferTarget = new XenoRenderTarget();
            FrameBuffer = new XenoTexture2D((int)XenoCore.DisplayWidth, (int)XenoCore.DisplayHeight);
            FrameDepth = new XenoTextureDepth((int)XenoCore.DisplayWidth, (int)XenoCore.DisplayHeight);
            Filters = new List<XenoFilter>();
            GL.ClearColor(Color.Black);
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;

        }
        public XenoFilter AddFilter
        {
            set
            {
                Filters.Add(value);
            }
        }
        /// <summary>Load resources here.</summary>
        /// <param name="e">Not used.</param>
        protected override void OnLoad(EventArgs e)
        {
            GL.ClearColor(System.Drawing.Color.Black);
            GL.Enable(EnableCap.DepthTest);
            DoInit();
        }

        public XenoNode RootNode()
        {
            return XenoCore.CurrentScene.RootNode;
        }

        public virtual void DoInit()
        {

        }

        public virtual void DoUpdate()
        {

        }
        public virtual void DoPreRender()
        {
        }
        public virtual void DoPostRender()
        {

        }

        protected override void  OnResize(EventArgs e)
        {
            GL.Viewport(ClientRectangle);
            Matrix4 projection = Matrix4.Perspective((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref projection);
        }
        /// <summary>
        /// Called when your window is resized. Set your viewport here. It is also
        /// a good place to set up your projection matrix (which probably changes
        /// along when the aspect ratio of your window).
        /// </summary>
        /// <param name="e">Contains information on the new Width and Size of the GameWindow.</param>


        protected override void  OnUpdateFrame(FrameEventArgs e)
{
 	          FrameTime = e.Time;
           
            DoUpdate();
            XenoCore.CurrentScene.UpdateGraph();

        }


        protected override void  OnRenderFrame(FrameEventArgs e)
{
 	            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            XenoCore.LightList = XenoCore.CurrentScene.RootNode.AllWithType(typeof(XenoMod_Light), null);

            if (Filters.Count > 0)
            {

                DoPreRender();
                
                XenoTexture2D prev = null;

                foreach (var filter in Filters)
                {

                    filter.PerformRender(XenoCore.CurrentScene, prev);
                    

                }

            }
            else
            {

                DoPreRender();

                XenoCore.CurrentScene.RootNode.PerformRender();

                DoPostRender();

            }
            Frame++;
            if (Environment.TickCount > NextTick)
            {
                Fps = Frame;
                NextTick = Environment.TickCount + 1000;
                Frame = 0;
                Console.WriteLine("FPS:" + Fps);
            }
            SwapBuffers();

        }

        int Frame = 0;
        int NextTick = 0;
        int Fps = 0;



    }

}